package com.project.create;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author: 陈刚
 * @blame:
 * @date: 2022/10/4 0:28
 **/
public class Gen {

    /**
     * 取得源码包物理文件
     *
     * @return
     */
    public static File getPackageDirectory(String model) {
        try {
            String path = model + File.separator + "src" + File.separator + "main" + File.separator + "java";
            File file = new File("");
            file = new File(file.getAbsolutePath(), path);
            if (!file.exists()) {throw new Exception(file.getAbsolutePath());}
            //file = new File(file.getAbsolutePath(),packageName.replaceAll("\\.", "\\"+File.separator));
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 自动识别生成 dao,service,serviceImpl,dto,controller
     *
     * @param pkgname       包名
     * @param className     实体类名称
     * @param tableName     表明
     * @param baseName      基础名称
     * @param dtoName       Dto名称
     * @param searchDtoName 搜索名称
     * @param createName    创建人
     * @param name          名称
     * @return
     */
    public static void generateCode(String pkgname, String className, String tableName, String baseName, String dtoName, String searchDtoName, String createName, String name) {
        Map<String, Object> map = new HashMap(20);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        map.put("time", format.format(new Date()));
        map.put("name", name);
        map.put("pkgname", pkgname);
        map.put("className", className);
        map.put("baseName", baseName);
        map.put("dtoName", dtoName);
        map.put("tableName", tableName);
        map.put("searchDtoName", searchDtoName);
        map.put("createName", createName);
        File pkgDir = getPackageDirectory("");
        String packageApiOne = File.separator + "com" + File.separator + "project" + File.separator + pkgname;
        //判断包是否存在，不存在创建
        File poDir1 = new File(pkgDir.getAbsolutePath(), packageApiOne + File.separator + "controller");
        if (!poDir1.exists()) {
            poDir1.mkdirs();
        }
        String clientPath = poDir1.getAbsolutePath() + "/" + className + "Controller.java";
        File clientDir = new File(clientPath);
        if (!clientDir.exists()) {
            createFile(map, "controller", clientPath);
        }
        //判断包是否存在，不存在创建
        File poDir2 = new File(pkgDir.getAbsolutePath(), packageApiOne + File.separator + "dto");
        if (!poDir2.exists()) {
            poDir2.mkdirs();
        }
        String dtoPath = poDir2.getAbsolutePath() + "/" + dtoName + ".java";
        File dtoDir = new File(dtoPath);
        if (!dtoDir.exists()) {
            createFile(map, "dto", dtoPath);
        }
        String searchDtoPath = poDir2.getAbsolutePath() + "/" + searchDtoName + ".java";
        File searchDtoDir = new File(searchDtoPath);
        if (!searchDtoDir.exists()) {
            createFile(map, "searchDto", searchDtoPath);
        }

        File poDir3 = new File(pkgDir.getAbsolutePath(), packageApiOne + File.separator + "domain" + File.separator +"service");
        if (!poDir3.exists()) {
            poDir3.mkdirs();
        }
        String servicePath = poDir3.getAbsolutePath() +  File.separator+"/" + className + "Service.java";
        File applicationDir = new File(servicePath);
        if (!applicationDir.exists()) {
            createFile(map, "service", servicePath);
        }

        //判断包是否存在，不存在创建
        File poDir4 = new File(pkgDir.getAbsolutePath(), packageApiOne + File.separator + "domain" + File.separator + "repository");
        if (!poDir4.exists()) {
            poDir4.mkdirs();
        }
        String repositoryPath = poDir4.getAbsolutePath() + "/" + className + "Repository.java";
        File repositoryDir = new File(repositoryPath);
        if (!repositoryDir.exists()) {
            createFile(map, "repository", repositoryPath);
        }
    }

    public static boolean createFile(Map<String, Object> map, String tempname, String filename) {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_27);
        //StringWriter sw = null;
        try {
            cfg.setDirectoryForTemplateLoading(ResourceUtils.getFile("classpath:templates"));
            //cfg.setClassForTemplateLoading(gen.class, "/codetemplate");

            cfg.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_27));
            Template temp = cfg.getTemplate(tempname + ".ftl");
            temp.setEncoding("UTF-8");
            File file = new File(filename);
            FileWriter fw = new FileWriter(file);
            //sw = new StringWriter();
            BufferedWriter bw = new BufferedWriter(fw);
            temp.process(map, bw);
            bw.flush();
            fw.close();
            System.out.println("》》》》》》》》》》》》》》创建创建" + tempname + "成功！！！");
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } catch (TemplateException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static void main(String[] args) {
        Gen s = new Gen();
        //包名
        String pkgname = "activity";
        //实体类名称
        String className = "ActivitySingupVote";
        //基础名称 接口拼接
        String baseName = "singupVote";
        //转换类DTO
        String dtoName = "ActivitySingupVoteDTO";
        //搜索类DTO
        String searchDtoName = "ActivitySingupVoteSearchDTO";
        //表名
        String tableName = "tb_activity_singup_vote";
        //创建人
        String createName = "陈刚";
        //名称
        String name = "活动报名图片";
        s.generateCode(pkgname, className, tableName, baseName, dtoName, searchDtoName, createName, name);
       /* String modle="pioneer-system"; //模块
        String pkgname="system"; //包名
        String className=""; //实体类名称
        String createName="chg"; //创建人
        String tableName = ""; //表名称
        String tableModel =""; //表名称
        //s.generateCode(modle,pkgname,className,tableName,createName,name);
        List<Class>  classList = getClasssFromPackage("com.nzrj.system.entity");
        for (int i=0;i<classList.size();i++) {
            //System.out.println("asdasdasdasdasd"+classList.get(i).toString());
            if(classList.get(i).toString().indexOf("$") == -1){
                Class clas=classList.get(i);
                Table annotation = (Table) clas.getAnnotation(Table.class);
                tableName = annotation.name();
                ApiModel apimodle=(ApiModel) clas.getAnnotation(ApiModel.class);
                tableModel= apimodle.description();
                className = clas.getSimpleName();
                generateCode(modle, pkgname, className, tableName, createName, tableModel);
            }
        }*/

    }

    /**
     * 获得包下面的所有的class
     *
     * @param pack package完整名称
     * @return List包含所有class的实例
     */
    public static List<Class> getClasssFromPackage(String pack) {
        List<Class> clazzs = new ArrayList<Class>();

        // 是否循环搜索子包
        boolean recursive = true;

        // 包名字
        String packageName = pack;
        // 包名对应的路径名称
        String packageDirName = packageName.replace('.', '/');

        Enumeration<URL> dirs;

        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {
                URL url = dirs.nextElement();

                String protocol = url.getProtocol();

                if ("file".equals(protocol)) {
                    System.out.println("file类型的扫描");
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    findClassInPackageByFile(packageName, filePath, recursive, clazzs);
                } else if ("jar".equals(protocol)) {
                    System.out.println("jar类型的扫描");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return clazzs;
    }

    /**
     * 在package对应的路径下找到所有的class
     *
     * @param packageName package名称
     * @param filePath    package对应的路径
     * @param recursive   是否查找子package
     * @param clazzs      找到class以后存放的集合
     */
    public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive, List<Class> clazzs) {
        File dir = new File(filePath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 在给定的目录下找到所有的文件，并且进行条件过滤
        File[] dirFiles = dir.listFiles(new FileFilter() {

            @Override
            public boolean accept(File file) {
                boolean acceptDir = recursive && file.isDirectory();// 接受dir目录
                boolean acceptClass = file.getName().endsWith("class");// 接受class文件
                return acceptDir || acceptClass;
            }
        });

        for (File file : dirFiles) {
            if (file.isDirectory()) {
                findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs);
            } else {
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
